package hid;

import java.util.HashMap;
import java.util.Map;

import core.Lunecy;
import util.common.AbstractManager;

import org.lwjgl.LWJGLException;
import org.lwjgl.input.Mouse;
import org.lwjgl.input.Keyboard;

/**
 * Internally records and abstracts the state of human
 * interface devices. Facilities are provided to re-map
 * keys.
 * @author Joel Rausch
 */
public class HIDManager extends AbstractManager {
	
	private Axis   xAxis;
	private Axis   yAxis;
	private Key    keyUp;
	private Key    keyDown;
	private Key    keyLeft;
	private Key    keyRight;
	private Map<Integer, Key> keyMap;
	
	/** Enumeration for functional keys. */
	public enum Keys {
		Key_Up,
		Key_Down,
		Key_Left,
		Key_Right
	}
	
	/** Enumeration for functional axes. */
	public enum Axes {
		MouseXAxis,
		MouseYAxis
	}

	/** Return true if the key is pressed. */
	public boolean isPressed(Keys key) {
		switch(key) {
		case Key_Up:
			return keyUp.isDown();
		case Key_Down:
			return keyDown.isDown();
		case Key_Left:
			return keyLeft.isDown();
		case Key_Right:
			return keyRight.isDown();
		default:
			return false;
		}
	}
	
	/** Returns the current axis reading. */
	public float axesValue(Axes axis) {
		switch(axis) {
		case MouseXAxis:
			return xAxis.poll();
		case MouseYAxis:
			return yAxis.poll();
		default:
			return 0;
		}
	}
	
	/** Update the internal HID state. Should be called every frame. */
	public void update() {
		// Update axis state with mouse delta
		xAxis.update(Mouse.getDX());
		yAxis.update(Mouse.getDY());
		
		// Update key state
		while(Keyboard.next()) {
			Integer key = new Integer(Keyboard.getEventKey());
			boolean pressed = Keyboard.getEventKeyState();
			Key keyWrapper = keyMap.get(key);
			if(keyWrapper != null) {
				keyWrapper.update(pressed);
			}
		}
	}

	@Override
	public void startup() throws LWJGLException {
		// Initialize input libraries
		Mouse.create();
		Mouse.setGrabbed(true);
		Keyboard.create();
		
		// Create mouse axes
		xAxis = new Axis(Axes.MouseXAxis);
		yAxis = new Axis(Axes.MouseYAxis);
		
		// Create keys and put in with default mapping.
		keyUp = new Key();
		keyDown = new Key();
		keyLeft = new Key();
		keyRight = new Key();
		keyMap = new HashMap<Integer, Key>();
		keyMap.put(new Integer(Keyboard.KEY_UP), keyUp);
		keyMap.put(new Integer(Keyboard.KEY_DOWN), keyDown);
		keyMap.put(new Integer(Keyboard.KEY_LEFT), keyLeft);
		keyMap.put(new Integer(Keyboard.KEY_RIGHT), keyRight);
		
		xAxis.setScale(0.01f);
		yAxis.setScale(0.01f);
	}

	@Override
	public void shutdown() {
		Mouse.destroy();
		Keyboard.destroy();
	}
}
